package com.fanco.learn_datastruct_leetcode.juc;

import java.util.concurrent.TimeUnit;

/**
 * @author qiaowang 2021/8/23
 * 描述: 通过Synchronized实现 等待通知 功能
 * 线程获取锁失败时，会先进行 wait()方法
 *
 * 等到另一个线程执行notifyAll方法，走完流程，原线程被唤醒后， 继续执行。 
    blocked和waiting的区别
    BLOCKED是锁竞争失败后被被动触发的状态[比如notify 了但是没竞争到锁]，WAITING是人为的主动触发的状态

BLCKED的唤醒时自动触发的，而WAITING状态是必须要通过特定的方法来主动唤醒 notify
 */
public class SynchronizeWaitNotifyDemo {
    public static void main(String[] args) {

        Object lock = "lock";

        Thread thread_1 = new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + "等待锁" + lock.toString());
                try {
                    lock.wait();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "被唤醒，继续运行....");
            }

        }, "Thread_1");
        thread_1.start();

        Thread thread_2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + "在运行");
                try {
                    // 线程2占用锁 2s
                    TimeUnit.SECONDS.sleep(2);

                    System.out.println(thread_1.getName() + "被唤醒前的状态是" + thread_1.getState());
                    //notifyAll的位置
                    lock.notifyAll();//将thread_1的线程状态从waiting->blocked

                    for (int i = 0; i < 5; i++) {
                        System.out.println("线程"+thread_1.getName()+"的状态是" + thread_1.getState());
                        try {
                            TimeUnit.SECONDS.sleep(1);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                    System.out.println(Thread.currentThread().getName()+"线程运行结束");
                    //notifyAll的位置
                    //lock.notifyAll();

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }, "Thread_2");
        thread_2.start();

    }
}
